package com.cskaoyan.market.service;

import com.cskaoyan.market.db.domain.*;
import com.cskaoyan.market.db.mapper.MarketCartMapper;
import com.cskaoyan.market.db.mapper.MarketCouponMapper;
import com.cskaoyan.market.db.mapper.MarketCouponUserMapper;
import com.cskaoyan.market.db.mapper.MarketGrouponRulesMapper;
import com.cskaoyan.market.vo.WxCouponUserVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Service
public class WxCouponServiceImpl implements WxCouponService {
    @Autowired
    MarketCouponMapper marketCouponMapper;

    @Autowired
    MarketCouponUserMapper marketCouponUserMapper;

    @Autowired
    MarketCartMapper marketCartMapper;

    @Autowired
    MarketGrouponRulesMapper marketGrouponRulesMapper;
    private final WxCartServiceImpl wxCartService;

    public WxCouponServiceImpl(WxCartServiceImpl wxCartService) {
        this.wxCartService = wxCartService;
    }

    @Override
    public List<MarketCoupon> list() {
        MarketCouponExample marketCouponExampleTimeType1 = new MarketCouponExample();
        marketCouponExampleTimeType1.createCriteria().andTypeEqualTo((short) 1).andStartTimeLessThan(LocalDateTime.now()).andEndTimeGreaterThan(LocalDateTime.now());
        MarketCouponExample marketCouponExampleTimeType2 = new MarketCouponExample();
        marketCouponExampleTimeType2.createCriteria().andTypeEqualTo((short) 0);
        List<MarketCoupon> marketCoupons1 = marketCouponMapper.selectByExample(marketCouponExampleTimeType1);
        List<MarketCoupon> marketCoupons2 = marketCouponMapper.selectByExample(marketCouponExampleTimeType2);
        if (marketCoupons1 != null && !marketCoupons1.isEmpty()) {
            marketCoupons1.addAll(marketCoupons2);
            return marketCoupons1;
        } else if (marketCoupons2 != null && !marketCoupons2.isEmpty()){
            return marketCoupons2;
        }else return new ArrayList<>();
    }

    @Override
    public List<WxCouponUserVo> mylist(Integer userId, Short status) {
        MarketCouponUserExample marketCouponUserExample = new MarketCouponUserExample();
        MarketCouponUserExample.Criteria criteria = marketCouponUserExample.createCriteria();
        criteria.andStatusEqualTo(status);
        criteria.andUserIdEqualTo(userId);
        List<MarketCouponUser> marketCouponUsers = marketCouponUserMapper.selectByExampleSelective(marketCouponUserExample, MarketCouponUser.Column.id, MarketCouponUser.Column.couponId, MarketCouponUser.Column.startTime, MarketCouponUser.Column.endTime);
        List<WxCouponUserVo> wxCouponUserVoList = new ArrayList<>();
        for (MarketCouponUser marketCouponUser : marketCouponUsers) {
            WxCouponUserVo wxCouponUserVo = new WxCouponUserVo();
            wxCouponUserVo.setId(marketCouponUser.getId());
            wxCouponUserVo.setStartTime(marketCouponUser.getStartTime());
            wxCouponUserVo.setEndTime(marketCouponUser.getEndTime());
            Integer couponId = marketCouponUser.getCouponId();
            wxCouponUserVo.setCid(couponId);
            MarketCoupon marketCoupon = marketCouponMapper.selectByPrimaryKey(couponId);
            wxCouponUserVo.setName(marketCoupon.getName());
            wxCouponUserVo.setTag(marketCoupon.getTag());
            wxCouponUserVo.setDesc(marketCoupon.getDesc());
            wxCouponUserVo.setMin(marketCoupon.getMin());
            wxCouponUserVo.setDiscount(marketCoupon.getDiscount());
            wxCouponUserVo.setAvailable(false);
            wxCouponUserVoList.add(wxCouponUserVo);
        }
        return wxCouponUserVoList;
    }

    @Override
    public Integer receive(Integer userId, Integer couponId) {
        MarketCoupon marketCoupon = marketCouponMapper.selectByPrimaryKey(couponId);
        if (marketCoupon == null) {
            return -1;
        }
        if (hasCoupon(userId, couponId)) {
            return 1;
        }
        MarketCouponUser marketCouponUser = new MarketCouponUser();
        marketCouponUser.setCouponId(couponId);
        marketCouponUser.setAddTime(LocalDateTime.now());
        if (marketCoupon.getTimeType() == 1) {
            marketCouponUser.setStartTime(marketCoupon.getStartTime());
            marketCouponUser.setEndTime(marketCoupon.getEndTime());
        } else {
            marketCouponUser.setStartTime(LocalDateTime.now());
            marketCouponUser.setEndTime(LocalDateTime.now().plusDays(marketCoupon.getDays()));
        }

        marketCouponUser.setUserId(userId);
        marketCouponUser.setStatus((short) 0);
        marketCouponUser.setDeleted(false);
        marketCouponUserMapper.insert(marketCouponUser);
        return 0;
    }

    private boolean hasCoupon(Integer userId, Integer couponId) {
        MarketCouponUserExample marketCouponUserExample = new MarketCouponUserExample();
        MarketCouponUserExample.Criteria criteria = marketCouponUserExample.createCriteria();
        criteria.andUserIdEqualTo(userId);
        criteria.andCouponIdEqualTo(couponId);
        int size = marketCouponUserMapper.selectByExample(marketCouponUserExample).size();
        return size != 0;
    }

    @Override
    public Integer exchange(Integer userId, String code) {
        MarketCouponExample marketCouponExample = new MarketCouponExample();
        marketCouponExample.createCriteria().andCodeEqualTo(code);
        List<MarketCoupon> marketCoupons = marketCouponMapper.selectByExample(marketCouponExample);
        if (marketCoupons.isEmpty()) {
            return -1;
        }
        for (MarketCoupon marketCoupon : marketCoupons) {
            Integer couponId = marketCoupon.getId();
            if (hasCoupon(userId, couponId)) return 1;
            MarketCouponUser marketCouponUser = new MarketCouponUser();
            marketCouponUser.setCouponId(couponId);
            marketCouponUser.setAddTime(LocalDateTime.now());
            if (marketCoupon.getTimeType() == 1) {
                marketCouponUser.setStartTime(marketCoupon.getStartTime());
                marketCouponUser.setEndTime(marketCoupon.getEndTime());
            } else {
                marketCouponUser.setStartTime(LocalDateTime.now());
                Short days = marketCoupon.getDays();
                marketCouponUser.setEndTime(marketCouponUser.getStartTime().plusDays(days));
            }
            marketCouponUser.setUserId(userId);
            marketCouponUser.setStatus((short) 0);
            marketCouponUser.setDeleted(false);
            marketCouponUserMapper.insert(marketCouponUser);
        }
        return 0;
    }

    @Override
    public List<WxCouponUserVo> selectlist(Integer cartId, Integer userId) {
        MarketCouponUserExample marketCouponUserExample = new MarketCouponUserExample();
        MarketCouponUserExample.Criteria criteria = marketCouponUserExample.createCriteria();
        criteria.andUserIdEqualTo(userId).andStatusEqualTo((short) 0);
        List<MarketCouponUser> marketCouponUsers = marketCouponUserMapper.selectByExample(marketCouponUserExample);
        List<WxCouponUserVo> wxCouponUserVoList = new ArrayList<>();
        for (MarketCouponUser marketCouponUser : marketCouponUsers) {
            WxCouponUserVo wxCouponUserVo = new WxCouponUserVo();
            wxCouponUserVo.setId(marketCouponUser.getId());
            wxCouponUserVo.setStartTime(marketCouponUser.getStartTime());
            wxCouponUserVo.setEndTime(marketCouponUser.getEndTime());
            Integer couponId = marketCouponUser.getCouponId();
            wxCouponUserVo.setCid(couponId);
            MarketCoupon marketCoupon = marketCouponMapper.selectByPrimaryKey(couponId);
            wxCouponUserVo.setName(marketCoupon.getName());
            wxCouponUserVo.setTag(marketCoupon.getTag());
            wxCouponUserVo.setDesc(marketCoupon.getDesc());
            wxCouponUserVo.setMin(marketCoupon.getMin());
            wxCouponUserVo.setDiscount(marketCoupon.getDiscount());
            BigDecimal price;
            if (cartId == 0) {
                List<MarketCart> marketCarts = wxCartService.getMarketCarts(userId);
                List<MarketCart> checkedCarts = wxCartService.getCheckedCarts(marketCarts);
                price = wxCartService.calculateTotalAmount(checkedCarts);
            } else {
                MarketCart marketCart = marketCartMapper.selectByPrimaryKey(cartId);
                price = marketCart.getPrice();
            }
            wxCouponUserVo.setAvailable(isAvailable(price, marketCoupon, marketCouponUser));
            wxCouponUserVoList.add(wxCouponUserVo);
        }
        return wxCouponUserVoList;
    }

    @Override
    public Integer couponProvide(Integer userId) {
        MarketCouponExample marketCouponExample = new MarketCouponExample();
        MarketCouponExample.Criteria criteria = marketCouponExample.createCriteria();
        criteria.andNameEqualTo("新用户优惠券");
        MarketCoupon marketCoupon = marketCouponMapper.selectOneByExampleSelective(marketCouponExample, MarketCoupon.Column.id);
        if (marketCoupon == null) {
            return -1;
        }
        return receive(userId, marketCoupon.getId());
    }

    @Override
    public void updateStatus(Integer id) {
        MarketCouponUserExample marketCouponUserExample = new MarketCouponUserExample();
        marketCouponUserExample.createCriteria().andUserIdEqualTo(id);
        List<MarketCouponUser> marketCouponUsers = marketCouponUserMapper.selectByExample(marketCouponUserExample);
        if(!marketCouponUsers.isEmpty()){
            for (MarketCouponUser marketCouponUser : marketCouponUsers) {
                // 如果优惠券的结束时间早于当前时间
                if (marketCouponUser.getEndTime().isBefore(LocalDateTime.now())) {
                    // 更新优惠券用户的状态为2
                    marketCouponUser.setStatus((short)2);
                    marketCouponUserMapper.updateByPrimaryKeySelective(marketCouponUser);
                }
            }
        }
    }

    private boolean isAvailable(BigDecimal price, MarketCoupon marketCoupon, MarketCouponUser marketCouponUser) {
        LocalDateTime now = LocalDateTime.now();
        if (now.isBefore(marketCouponUser.getStartTime()) || now.isAfter(marketCouponUser.getEndTime())) {
            return false;
        }
        if (price.compareTo(marketCoupon.getMin()) < 0) {
            return false;
        }
        return true;
    }
}
